iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
0
Blockchain

又LAG的EOS.IO技術筆記系列 第 6

乙太坊經典範例 - 寵物商店(下)

  • 分享至 

  • xImage
  •  

還沒看過悲重寫的上篇....可以先去看看/images/emoticon/emoticon02.gif

OK,今天帶來的是倖存的下篇。今天會正式進到程式碼的部份。不多說,直接開始吧!

Let's GO

最後會附上完整程式碼,可以往下複製使用 (由於語法屬於舊式,不是很建議大伙深入探討程式)。

初始化專案

安裝 truffle (乙太坊開發框架)。

npm install -g truffle

建立專案目錄

mkdir pet-shop-tutorial

cd pet-shop-tutorial

初始化範例程式

truffle unbox pet-shop

撰寫智能合約

contract目錄下,建立Adoption.sol檔案,並輸入以下程式:

pragma solidity ^0.5.0;

contract Adoption {
  address[16] public adopters;

  // Adopting a pet
  function adopt(uint petId) public returns (uint) {
    require(petId >= 0 && petId <= 15);

    adopters[petId] = msg.sender;

    return petId;
  }

  // Retrieving the adopters
  function getAdopters() public view returns (address[16] memory) {
    return adopters;
  }

}

編譯智能合約

truffle compile

會得到類似下面輸出。

Compiling your contracts...
===========================
> Compiling ./contracts/Adoption.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /Users/cruzmolina/Code/truffle-projects/metacoin/build/contracts
> Compiled successfully using:
   - solc: 0.5.0+commit.1d4f565a.Emscripten.clang

部署智能合約

接著在migrations/資料夾下新增2_deploy_contracts.js檔案,並寫入下面內容:

var Adoption = artifacts.require("Adoption");

module.exports = function(deployer) {
  deployer.deploy(Adoption);
};

然後下命令truffle migrate,會得到類似結果:

  1_initial_migration.js
  ======================

     Deploying 'Migrations'
     ----------------------
     > transaction hash:    0x3b558e9cdf1231d8ffb3445cb2f9fb01de9d0363e0b97a17f9517da318c2e5af
     > Blocks: 0            Seconds: 0
     > contract address:    0x5ccb4dc04600cffA8a67197d5b644ae71856aEE4
     > account:             0x8d9606F90B6CA5D856A9f0867a82a645e2DfFf37
     > balance:             99.99430184
     > gas used:            284908
     > gas price:           20 gwei
     > value sent:          0 ETH
     > total cost:          0.00569816 ETH


     > Saving migration to chain.
     > Saving artifacts
     -------------------------------------
     > Total cost:          0.00569816 ETH


  2_deploy_contracts.js
  =====================

     Deploying 'Adoption'
     .............................
     .............................

前端交互界面(網頁)

現在,我們有了區塊鏈網路,有了區塊鏈錢包,有了合約,再來是需要與合約互動的方式。編輯src/js/app.js,改成以下內容:

App = {
  web3Provider: null,
  contracts: {},

  init: async function() {
    // Load pets.
    $.getJSON('../pets.json', function(data) {
      var petsRow = $('#petsRow');
      var petTemplate = $('#petTemplate');

      for (i = 0; i < data.length; i ++) {
        petTemplate.find('.panel-title').text(data[i].name);
        petTemplate.find('img').attr('src', data[i].picture);
        petTemplate.find('.pet-breed').text(data[i].breed);
        petTemplate.find('.pet-age').text(data[i].age);
        petTemplate.find('.pet-location').text(data[i].location);
        petTemplate.find('.btn-adopt').attr('data-id', data[i].id);

        petsRow.append(petTemplate.html());
      }
    });

    return await App.initWeb3();
  },

  initWeb3: async function() {
    // Modern dapp browsers...
    if (window.ethereum) {
      App.web3Provider = window.ethereum;
      try {
        // Request account access
        await window.ethereum.enable();
      } catch (error) {
        // User denied account access...
        console.error("User denied account access");
      }
    }
    // Legacy dapp browsers...
    else if (window.web3) {
      App.web3Provider = window.web3.currentProvider;
    }
    // If no injected web3 instance is detected, fall back to Ganache
    else {
      App.web3Provider = new Web3.providers.HttpProvider('http://eos.cloudlab.mywire.org:7545');
    }
    web3 = new Web3(App.web3Provider);


    return App.initContract();
  },

  initContract: function() {
    $.getJSON('Adoption.json', function(data) {
      // Get the necessary contract artifact file and instantiate it with truffle-contract
      var AdoptionArtifact = data;
      App.contracts.Adoption = TruffleContract(AdoptionArtifact);

      // Set the provider for our contract
      App.contracts.Adoption.setProvider(App.web3Provider);

      // Use our contract to retrieve and mark the adopted pets
      return App.markAdopted();
    });

    return App.bindEvents();
  },

  bindEvents: function() {
    $(document).on('click', '.btn-adopt', App.handleAdopt);
  },

  markAdopted: function(adopters, account) {
    var adoptionInstance;

    App.contracts.Adoption.deployed().then(function(instance) {
      adoptionInstance = instance;

      return adoptionInstance.getAdopters.call();
    }).then(function(adopters) {
      for (i = 0; i < adopters.length; i++) {
        if (adopters[i] !== '0x0000000000000000000000000000000000000000') {
          $('.panel-pet').eq(i).find('button').text('Success').attr('disabled', true);
        }
      }
    }).catch(function(err) {
      console.log(err.message);
    });
  },

  handleAdopt: function(event) {
    event.preventDefault();

    var petId = parseInt($(event.target).data('id'));
    var adoptionInstance;

    web3.eth.getAccounts(function(error, accounts) {
      if (error) {
        console.log(error);
      }

      var account = accounts[0];

      App.contracts.Adoption.deployed().then(function(instance) {
        adoptionInstance = instance;

        // Execute adopt as a transaction by sending account
        return adoptionInstance.adopt(petId, {from: account});
      }).then(function(result) {
        return App.markAdopted();
      }).catch(function(err) {
        console.log(err.message);
      });
    });

  }

};

$(function() {
  $(window).load(function() {
    App.init();
  });
});

來運行看看npm run dev。應該會自動開啟瀏覽器瀏覽http://localhost:3000,並且MetaMask會要求登入。
https://ithelp.ithome.com.tw/upload/images/20190922/20112470uVAcU5u3c5.png
※ 你可能要先執行npm install

允許後每隻狗狗就可以進行領養囉(Adopt)。


關於DApp

DApp的意思是分散式應用程式,就簡單理解為區塊鏈上智能合約的應用程式就好。目前大多數DApp還是以網頁形式與使用者互動。這之中還有一些技術細節,已有有需要在提。

多數DApp的基本架構

那麼關於這次範例的DApp的組成:

組件 軟體 備註說明
區塊鏈底層 Ganache 乙太坊區塊鏈網路
區塊鏈虛擬機 Ganache 乙太坊虛擬機(EVM)。提供智能合約執行的環境
智能合約 Soilidty 本次合約程式內容
瀏覽器畫面 HTML5+Web3.js Web3.js是使瀏覽器與乙太坊錢包溝通的橋樑

※ 我正式接觸乙太坊是在EOS之後,並且也不算太深入,不過許多概念可以相通。未來會以EOS來說。


上一篇
乙太坊經典範例 - 寵物商店(上)
下一篇
硬分岔&軟分岔
系列文
又LAG的EOS.IO技術筆記31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言